/**
 * Copyright 2009, O. Menéndez (omenen@gmail.com)
 * 
 * This file is part of SWTLayoutTest.
 * 
 * SWTLayoutTest is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * SWTLayoutTest is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the iimplied warranty of
 * MERCHANTABILITY or FITENSS FOR A PARTICULAR PURPIOSE. See the GNU General
 * Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * SWTLayoutTest. If not, see <http://www.gnu.org/licenses/>
 */
package com.googlecode.swtlayouttest;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
	public static final String ID = "com.googlecode.swtlayouttest.view";
	
	private static final int NUM_LABELS = 20;
	private static final Color s_colors [] = {
		  Display.getDefault().getSystemColor(SWT.COLOR_CYAN),
		  Display.getDefault().getSystemColor(SWT.COLOR_GREEN),
		  Display.getDefault().getSystemColor(SWT.COLOR_MAGENTA),
		  Display.getDefault().getSystemColor(SWT.COLOR_RED),
		  Display.getDefault().getSystemColor(SWT.COLOR_WHITE),
		  Display.getDefault().getSystemColor(SWT.COLOR_DARK_YELLOW),
		  Display.getDefault().getSystemColor(SWT.COLOR_DARK_CYAN)
	};
	
	private Composite m_displayArea = null;
	private GridLayout m_containerLayout = null;
	private List<GridData> m_gridDatas = null;

	
	private Combo m_labelSelector = null;
	private Combo m_horizontalAlignmentCombo = null;
	private Combo m_verticalAlignmentCombo = null;
	private Text m_horizontalIndentText = null;
	private Text m_verticalIndentText = null;
	private Text m_horizontalSpanText = null;
	private Text m_verticalSpanText = null;
	private Button m_grabExcessHorizontalSpaceButton = null;
	private Button m_grabExcessVerticalSpaceButton = null;


	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		Composite area = new Composite(parent, SWT.NONE);
		area.setLayout(new GridLayout());
		
		Composite controlArea = new Composite(area, SWT.NONE);
		
		m_displayArea = createDisplayArea(area);
		
		controlArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		m_displayArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		setControls(controlArea);
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		// Do nothing
	}
	
	/**
	 * Creates the controls to populate the control area
	 * 
	 * @param area - graphical component to be populated
	 */
	private void setControls(Composite area)
	{
		area.setLayout(new GridLayout(2, false));
		
		Group containerGroup = new Group(area, SWT.NONE);
		containerGroup.setText("Container Layout");
		containerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		setContainerLayoutControls(containerGroup);
		
		
		Group labelsGroup = new Group(area, SWT.NONE);
		labelsGroup.setText("Labels GridData");
		labelsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		setLabelsGridDataControls(labelsGroup);
	}
	
	/**
	 * Creates the controls in charge of modifying container layout
	 * 
	 * @param group - graphical component to be populated
	 */
	private void setContainerLayoutControls(Group group)
	{
		group.setLayout(new GridLayout(4, false));

		/*
		 * Num columns
		 */
		Label numColumnsLabel = new Label(group, SWT.NONE);
		numColumnsLabel.setText("numColumns:");
		numColumnsLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text numColumnsText = new Text(group, SWT.BORDER);
		numColumnsText.setText(Integer.toString(m_containerLayout.numColumns));
		numColumnsText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		
		/*
		 * Columns equal width
		 */
		final Button makeColumnsEqualWidthButton = new Button(group, SWT.CHECK);
		makeColumnsEqualWidthButton.setText("makeColumnsEqualWidth");
		makeColumnsEqualWidthButton.setSelection(m_containerLayout.makeColumnsEqualWidth);
		GridData makeColumnsEqualWidthButtonGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
		makeColumnsEqualWidthButtonGridData.horizontalSpan = 2;
		makeColumnsEqualWidthButton.setLayoutData(makeColumnsEqualWidthButtonGridData);

		/*
		 * Horizontal spacing
		 */
		Label horizontalSpacingLabel = new Label(group, SWT.NONE);
		horizontalSpacingLabel.setText("horizontalSpacing:");
		horizontalSpacingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text horizontalSpacingText = new Text(group, SWT.BORDER);
		horizontalSpacingText.setText(Integer.toString(m_containerLayout.horizontalSpacing));
		horizontalSpacingText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Vertical spacing
		 */
		Label verticalSpacingLabel = new Label(group, SWT.NONE);
		verticalSpacingLabel.setText("verticalSpacing:");
		verticalSpacingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text verticalSpacingText = new Text(group, SWT.BORDER);
		verticalSpacingText.setText(Integer.toString(m_containerLayout.verticalSpacing));
		verticalSpacingText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin width
		 */
		Label marginWidthLabel = new Label(group, SWT.NONE);
		marginWidthLabel.setText("marginWidth:");
		marginWidthLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginWidthText = new Text(group, SWT.BORDER);
		marginWidthText.setText(Integer.toString(m_containerLayout.marginWidth));
		marginWidthText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin height
		 */
		Label marginHeightLabel = new Label(group, SWT.NONE);
		marginHeightLabel.setText("marginHeight:");
		marginHeightLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginHeightText = new Text(group, SWT.BORDER);
		marginHeightText.setText(Integer.toString(m_containerLayout.marginHeight));
		marginHeightText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin left
		 */
		Label marginLeftLabel = new Label(group, SWT.NONE);
		marginLeftLabel.setText("marginLeft:");
		marginLeftLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginLeftText = new Text(group, SWT.BORDER);
		marginLeftText.setText(Integer.toString(m_containerLayout.marginLeft));
		marginLeftText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin top
		 */
		Label marginTopLabel = new Label(group, SWT.NONE);
		marginTopLabel.setText("marginTop:");
		marginTopLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginTopText = new Text(group, SWT.BORDER);
		marginTopText.setText(Integer.toString(m_containerLayout.marginTop));
		marginTopText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin right
		 */
		Label marginRightLabel = new Label(group, SWT.NONE);
		marginRightLabel.setText("marginRight:");
		marginRightLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginRightText = new Text(group, SWT.BORDER);
		marginRightText.setText(Integer.toString(m_containerLayout.marginRight));
		marginRightText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Margin bottom
		 */
		Label marginBottomLabel = new Label(group, SWT.NONE);
		marginBottomLabel.setText("marginBottom:");
		marginBottomLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		final Text marginBottomText = new Text(group, SWT.BORDER);
		marginBottomText.setText(Integer.toString(m_containerLayout.marginBottom));
		marginBottomText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Apply button
		 */
		Button applyButton = new Button(group, SWT.PUSH);
		applyButton.setText("Apply");
		GridData applyButtonGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
		applyButtonGridData.horizontalSpan = 4;
		applyButton.setLayoutData(applyButtonGridData);
		applyButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				m_containerLayout.numColumns = Integer.parseInt(numColumnsText.getText());
				m_containerLayout.makeColumnsEqualWidth = makeColumnsEqualWidthButton.getSelection();
				m_containerLayout.horizontalSpacing = Integer.parseInt(horizontalSpacingText.getText());
				m_containerLayout.verticalSpacing = Integer.parseInt(verticalSpacingText.getText());
				m_containerLayout.marginWidth = Integer.parseInt(marginWidthText.getText());
				m_containerLayout.marginHeight = Integer.parseInt(marginHeightText.getText());
				m_containerLayout.marginLeft = Integer.parseInt(marginLeftText.getText());
				m_containerLayout.marginRight = Integer.parseInt(marginRightText.getText());
				m_containerLayout.marginTop = Integer.parseInt(marginTopText.getText());
				m_containerLayout.marginBottom = Integer.parseInt(marginBottomText.getText());
				
				m_displayArea.layout();
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// Do nothing
			}
		});
	}

	/**
	 * Creates the controls in charge of modifying labels' grid data
	 * 
	 * @param group - graphical component to be populated
	 */
	private void setLabelsGridDataControls(Group group)
	{
		group.setLayout(new GridLayout(4, false));

		/*
		 * Label selector
		 */
		m_labelSelector = new Combo(group, SWT.READ_ONLY);
		for (int i = 1; i <= NUM_LABELS; i++)
		{
			m_labelSelector.add("Label " + i);
		}
		GridData labelSelectorGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
		labelSelectorGridData.horizontalSpan = 4;
		m_labelSelector.setLayoutData(labelSelectorGridData);

		/*
		 * Horizontal alignment
		 */
		Label horizontalAlignmentLabel = new Label(group, SWT.NONE);
		horizontalAlignmentLabel.setText("horizontalAlignment:");
		horizontalAlignmentLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_horizontalAlignmentCombo = new Combo(group, SWT.READ_ONLY);
		m_horizontalAlignmentCombo.add("SWT.FILL");
		m_horizontalAlignmentCombo.add("SWT.CENTER");
		m_horizontalAlignmentCombo.add("SWT.LEFT");
		m_horizontalAlignmentCombo.add("SWT.RIGHT");
		m_horizontalAlignmentCombo.select(0);
		m_horizontalAlignmentCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Vertical alignment
		 */
		Label verticalAlignmentLabel = new Label(group, SWT.NONE);
		verticalAlignmentLabel.setText("verticalAlignment:");
		verticalAlignmentLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_verticalAlignmentCombo = new Combo(group, SWT.READ_ONLY);
		m_verticalAlignmentCombo.add("SWT.FILL");
		m_verticalAlignmentCombo.add("SWT.CENTER");
		m_verticalAlignmentCombo.add("SWT.TOP");
		m_verticalAlignmentCombo.add("SWT.BOTTOM");
		m_verticalAlignmentCombo.select(0);
		m_verticalAlignmentCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		/*
		 * Horizontal indent
		 */
		Label horizontalIndentLabel = new Label(group, SWT.NONE);
		horizontalIndentLabel.setText("horizontalIndent:");
		horizontalIndentLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_horizontalIndentText = new Text(group, SWT.BORDER);
		m_horizontalIndentText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

		/*
		 * Vertical indent
		 */
		Label verticalIndentLabel = new Label(group, SWT.NONE);
		verticalIndentLabel.setText("verticalIndent:");
		verticalIndentLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_verticalIndentText = new Text(group, SWT.BORDER);
		m_verticalIndentText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

		/*
		 * Horizontal span
		 */
		Label horizontalSpanLabel = new Label(group, SWT.NONE);
		horizontalSpanLabel.setText("horizontalSpan:");
		horizontalSpanLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_horizontalSpanText = new Text(group, SWT.BORDER);
		m_horizontalSpanText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

		/*
		 * Vertical span
		 */
		Label verticalSpanLabel = new Label(group, SWT.NONE);
		verticalSpanLabel.setText("verticalSpan:");
		verticalSpanLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		
		m_verticalSpanText = new Text(group, SWT.BORDER);
		m_verticalSpanText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

		/*
		 * Grab excess horizontal space
		 */
		m_grabExcessHorizontalSpaceButton = new Button(group, SWT.CHECK);
		m_grabExcessHorizontalSpaceButton.setText("grabExcessHorizontalSpace");
		GridData grabExcessHorizontalSpaceButtonGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
		grabExcessHorizontalSpaceButtonGridData.horizontalSpan = 2;
		m_grabExcessHorizontalSpaceButton.setLayoutData(grabExcessHorizontalSpaceButtonGridData);

		/*
		 * Grab excess vertical space
		 */
		m_grabExcessVerticalSpaceButton = new Button(group, SWT.CHECK);
		m_grabExcessVerticalSpaceButton.setText("grabExcessVerticalSpace");
		GridData grabExcessVerticalSpaceButtonGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
		grabExcessVerticalSpaceButtonGridData.horizontalSpan = 2;
		m_grabExcessVerticalSpaceButton.setLayoutData(grabExcessVerticalSpaceButtonGridData);

		/*
		 * Apply button
		 */
		Button applyButton = new Button(group, SWT.PUSH);
		applyButton.setText("Apply");
		GridData applyButtonGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
		applyButtonGridData.horizontalSpan = 4;
		applyButton.setLayoutData(applyButtonGridData);
		
		/*
		 * Listeners to show/modify configuration
		 */
		m_labelSelector.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				showGridData(getSelectedGridData());
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// Do nothing
			}
		});
		
		applyButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				GridData gridData = getSelectedGridData();
				int horizontalAlignment = -1;
				int verticalAlignment = -1;

				switch (m_horizontalAlignmentCombo.getSelectionIndex())
				{
				case 0:
					horizontalAlignment = SWT.FILL;
					break;
				case 1:
					horizontalAlignment = SWT.CENTER;
					break;
				case 2:
					horizontalAlignment = SWT.LEFT;
					break;
				case 3:
					horizontalAlignment = SWT.RIGHT;
					break;
				}
				
				switch (m_verticalAlignmentCombo.getSelectionIndex())
				{
				case 0:
					verticalAlignment = SWT.FILL;
					break;
				case 1:
					verticalAlignment = SWT.CENTER;
					break;
				case 2:
					verticalAlignment = SWT.TOP;
					break;
				case 3:
					verticalAlignment = SWT.BOTTOM;
					break;
				}
				
				gridData.horizontalAlignment = horizontalAlignment;
				gridData.verticalAlignment = verticalAlignment;
				gridData.horizontalIndent = Integer.parseInt(m_horizontalIndentText.getText());
				gridData.verticalIndent = Integer.parseInt(m_verticalIndentText.getText());
				gridData.horizontalSpan = Integer.parseInt(m_horizontalSpanText.getText());
				gridData.verticalSpan = Integer.parseInt(m_verticalSpanText.getText());
				gridData.grabExcessHorizontalSpace = m_grabExcessHorizontalSpaceButton.getSelection();
				gridData.grabExcessVerticalSpace = m_grabExcessVerticalSpaceButton.getSelection();
				
				m_displayArea.layout();
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// Do nothing
			}
		});

		/*
		 * Initialize content
		 */
		m_labelSelector.select(0);
		showGridData(getSelectedGridData());
	}
	
	/**
	 * Obtains the GridData associated to the label selected by 'm_labelSelector'
	 * 
	 * @param group - the GridData associated to the selected label
	 */
	private GridData getSelectedGridData()
	{
		return m_gridDatas.get(m_labelSelector.getSelectionIndex());
	}
	
	/**
	 * Shows the content of the GridData passed as parameter
	 * 
	 * @param gridData - GridData to be shown
	 */
	private void showGridData(GridData gridData)
	{
		switch (gridData.horizontalAlignment)
		{
		case SWT.FILL:
			m_horizontalAlignmentCombo.select(0);
			break;
		case SWT.CENTER:
			m_horizontalAlignmentCombo.select(1);
			break;
		case SWT.LEFT:
			m_horizontalAlignmentCombo.select(2);
			break;
		case SWT.RIGHT:
			m_horizontalAlignmentCombo.select(3);
			break;
		}
		
		switch (gridData.verticalAlignment)
		{
		case SWT.FILL:
			m_verticalAlignmentCombo.select(0);
			break;
		case SWT.CENTER:
			m_verticalAlignmentCombo.select(1);
			break;
		case SWT.TOP:
			m_verticalAlignmentCombo.select(2);
			break;
		case SWT.BOTTOM:
			m_verticalAlignmentCombo.select(3);
			break;
		}
		
		m_horizontalIndentText.setText(Integer.toString(gridData.horizontalIndent));
		m_verticalIndentText.setText(Integer.toString(gridData.verticalIndent));

		m_horizontalSpanText.setText(Integer.toString(gridData.horizontalSpan));
		m_verticalSpanText.setText(Integer.toString(gridData.verticalSpan));

		m_grabExcessHorizontalSpaceButton.setSelection(gridData.grabExcessHorizontalSpace);
		m_grabExcessVerticalSpaceButton.setSelection(gridData.grabExcessVerticalSpace);
	}
		
	/**
	 * Creates the area where the labels are placed as well as the container
	 * layout to be modified
	 * 
	 * @param parent - graphical component where the area will be placed
	 * @return the display area with the labels embedded
	 */
	private Composite createDisplayArea(Composite parent)
	{
		Composite area = new Composite(parent, SWT.BORDER);
		area.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
		m_containerLayout = new GridLayout(4, false);
		area.setLayout(m_containerLayout);
		
		m_gridDatas = new ArrayList<GridData>();
		
		for (int i = 1; i <= NUM_LABELS; i++)
		{
			Label label = new Label(area, SWT.BORDER);
			label.setText("Label " + i);
			label.setBackground(s_colors[i % s_colors.length]);
			
			GridData gridData = new GridData(SWT.CENTER, SWT.CENTER, false, false);
			label.setLayoutData(gridData);
			
			m_gridDatas.add(gridData);
		}

		return area;	
	}
}